//
//  KzTcpListener.swift
//  Trans
//
//  Created by zcj on 2024/12/31.
//

import Foundation
import Network
import NetAction

class KzTcpListener:TCPListenDelegate{
    //存放connection的容器
    public var conDic : KzMutableDic<ConId,KzConMsg> = KzMutableDic<ConId,KzConMsg>(dic: Dictionary(), state: false)
    var connectionTimer:Timer? //链接的检查定时器
    var updateTimer:Timer? //更新filedic的数据到UI的定时器
    var tcpListen:TCPListen
    var dealDataDlg:DealNetDataProtocol
    
    public init(port: UInt16, sta: Int32,dnpdlg:DealNetDataProtocol){
        tcpListen = TCPListen(port: port, sta: sta)
        dealDataDlg = dnpdlg
    }
    public func prepare(port: UInt16, sta: Int32,dnpdlg:DealNetDataProtocol){
        if tcpListen.listener.state == .cancelled{
            tcpListen = TCPListen(port: port, sta: sta)
            dealDataDlg = dnpdlg
        }
    }
    
    public func start(){
        tcpListen.delegate = self
        tcpListen.start()
    }
    
    public func close(){
        tcpListen.delegate = nil
        tcpListen.close()
    }
    
    func receiveConAndData(connection: NWConnection, data: Data) {
        let id = self.getConnectionId(con: connection)
        var finData = data
       
        if let conMsg = conDic[id] {
            conMsg.update()
            conMsg.lastData.append(data)
            finData = conMsg.lastData
            conMsg.lastData = Data()
        }else{
           let newConMsg = KzConMsg(con: connection)
            conDic[id] = newConMsg
        }
        
        //交给其他的类去实现更加细致的处理。
        dealDataDlg.receiveData(id: id, data: finData)
        
    }
    
    //实现对于connection 的hash值获取,作为id，改为使用ip
    func getConnectionId(con:NWConnection) -> ConId{
//        let id = Cal.hashObIden(iden: ObjectIdentifier(con))
        let ip = getipFromEndpoint(addr: con.endpoint.debugDescription)
        let id = Cal.hashOfString(str: ip)
        return id
    }
    
    func ListenReady() {
        self.monitorConnectionWithTimer()//监视连接的最后通信时间
        self.updateDataArray()//更新数据
        self.monitorNetwork()//监视网络是否断开
    }
    
    func ListenFailed() {
        self.connectionTimer?.invalidate()
        self.updateTimer?.invalidate()
    }
    
  
    //#####################################
    //定时监视connection的生命周期
    func monitorConnectionWithTimer(){
        self.connectionTimer = Timer(timeInterval: 3, repeats: true, block: { Timer in
            self.closeConnectionTimeOut()
        })
        if self.connectionTimer != nil{
            RunLoop.main.add(self.connectionTimer!, forMode: .common)
        }
    }
    
    func updateDataArray(){
        self.updateTimer = Timer(timeInterval: 1, repeats: true, block: { Timer in
            self.updateData()
        })
        if self.updateTimer != nil{
            RunLoop.main.add(self.updateTimer!, forMode: .common)
        }
    }
    
    
    //主动关闭连接
    func closeConnectionTimeOut(){
        //如果间隔最后一次发送信息的时间超过了timeout分钟就断开连接
        let timeoutLine:TimeInterval = Date().timeIntervalSince1970 - timeoutInterval
        let arr = conDic.keys()
        for key in arr {
            if conDic[key]!.timeStamp < timeoutLine{
                //关闭connection
                self.closeConnection(id: key)
            }
        }
    }
    
    func closeConnection(id:ConId){
        if let cm = conDic[id]{
            cm.con.cancel()
            conDic.removeValue(key: id)
        }
    }
    
    
    //更新信息
    func updateData(){
        if fileDownloadArr.array.count > 0{
            fileDownloadArr.updateData()
        }
        if fileUploadArr.array.count > 0{
            fileUploadArr.updateData()
        }
    }
    //#####################################
    func monitorNetwork(){
        // 启动 NWPathMonitor 监控网络状态
        var pathMonitor = NWPathMonitor()
        pathMonitor.pathUpdateHandler = { path in
            if path.status == .satisfied {
                print("Network is available")
            } else {
                //网络断开
                print("Network is not available")
                self.connectionTimer?.invalidate()
                self.conDic.removeAll()
            }
        }
        pathMonitor.start(queue: .global())
    }
}
